import { Repository } from "typeorm";
import { PathRegConst, isNone } from "st-common-core";
import { Menu } from "../entities/Menu";
import { MenuTypeEnum } from "../enums/menu-type.enum";
import { MenuEntityPropNameEnum } from "../enums/menu-entity-prop-name.enum";
import { MenuEntityPropValLimitConst } from "../consts/menu-entity-prop-val-limit.const";

export const MenuVerifyUtil: Record<string, {
  verify: (menu: Menu, menuRepository?: Repository<Menu>) => Promise<boolean>,
  message: string
}> = {
  [MenuEntityPropNameEnum.PARENT_ID]: {
    verify: async (menu: Menu, menuRepository: Repository<Menu>) => {
      // 如果当前菜单没有设置父级菜单，则直接校验通过
      if (isNone(menu[MenuEntityPropNameEnum.PARENT_ID])) return true;
      // 如果当前菜单设置了父级菜单，则校验父级菜单是否存在
      const parentCount = await menuRepository.count({
        where: {
          [MenuEntityPropNameEnum.ID]: menu[MenuEntityPropNameEnum.PARENT_ID]
        }
      });
      return parentCount > 0;
    },
    message: "父级菜单不存在"
  },
  [MenuEntityPropNameEnum.TYPE]: {
    verify: async (menu: Menu) => {
      return !isNone(menu[MenuEntityPropNameEnum.TYPE]) &&
        MenuEntityPropValLimitConst[MenuEntityPropNameEnum.TYPE].values.includes(menu[MenuEntityPropNameEnum.TYPE]);
    },
    message: "菜单类型不存在"
  },
  [MenuEntityPropNameEnum.NAME]: {
    verify: async (menu: Menu, menuRepository: Repository<Menu>) => {
      // 如果菜单名称长度不合法，则校验失败
      if (
        isNone(menu[MenuEntityPropNameEnum.NAME]) ||
        menu[MenuEntityPropNameEnum.NAME].length < MenuEntityPropValLimitConst[MenuEntityPropNameEnum.NAME].minLength ||
        menu[MenuEntityPropNameEnum.NAME].length > MenuEntityPropValLimitConst[MenuEntityPropNameEnum.NAME].maxLength
      ) return false;
      // 校验菜单名称是否已存在
      // 根据菜单名称查询菜单信息
      const menusFound = await menuRepository.find({
        where: {
          [MenuEntityPropNameEnum.NAME]: menu[MenuEntityPropNameEnum.NAME]
        }
      });
      // 如果查询结果为空，则校验通过，或者查询出来的菜单信息中，只有当前要更新的菜单，也校验通过
      return menusFound.length === 0 || (menusFound.length === 1 && menusFound[0][MenuEntityPropNameEnum.ID] === menu[MenuEntityPropNameEnum.ID]);
    },
    message: `菜单名称已存在或菜单名称长度不合法（应在 ${MenuEntityPropValLimitConst[MenuEntityPropNameEnum.NAME].minLength} - ${MenuEntityPropValLimitConst[MenuEntityPropNameEnum.NAME].maxLength} 个字符之间）`
  },
  [MenuEntityPropNameEnum.PAGE_PATH]: {
    verify: async (menu: Menu) => {
      // 对于菜单和 iframe 类型外的其他类型，无需校验页面路径
      if (
        menu[MenuEntityPropNameEnum.TYPE] !== MenuTypeEnum.MENU &&
        menu[MenuEntityPropNameEnum.TYPE] !== MenuTypeEnum.IFRAME
      ) return true;
      return !isNone(menu[MenuEntityPropNameEnum.PAGE_PATH]) &&
        menu[MenuEntityPropNameEnum.PAGE_PATH].length >= MenuEntityPropValLimitConst[MenuEntityPropNameEnum.PAGE_PATH].minLength &&
        menu[MenuEntityPropNameEnum.PAGE_PATH].length <= MenuEntityPropValLimitConst[MenuEntityPropNameEnum.PAGE_PATH].maxLength &&
        PathRegConst.VUE_COMPONENT_PATH_REG.test(menu[MenuEntityPropNameEnum.PAGE_PATH]);
    },
    message: `页面路径不合法（符合规范外，长度还需应在 ${MenuEntityPropValLimitConst[MenuEntityPropNameEnum.PAGE_PATH].minLength} - ${MenuEntityPropValLimitConst[MenuEntityPropNameEnum.PAGE_PATH].maxLength} 个字符之间）`
  },
  [MenuEntityPropNameEnum.ROUTE_NAME]: {
    verify: async (menu: Menu, menuRepository: Repository<Menu>) => {
      // 如果菜单类型不为菜单和 iframe，则无需校验路由名称
      if (
        menu[MenuEntityPropNameEnum.TYPE] !== MenuTypeEnum.MENU &&
        menu[MenuEntityPropNameEnum.TYPE] !== MenuTypeEnum.IFRAME
      ) return true;
      // 如果长度不合法，则校验失败
      if (
        isNone(menu[MenuEntityPropNameEnum.ROUTE_NAME]) ||
        menu[MenuEntityPropNameEnum.ROUTE_NAME].length < MenuEntityPropValLimitConst[MenuEntityPropNameEnum.ROUTE_NAME].minLength ||
        menu[MenuEntityPropNameEnum.ROUTE_NAME].length > MenuEntityPropValLimitConst[MenuEntityPropNameEnum.ROUTE_NAME].maxLength
      ) return false;
      // 校验路由名称是否已存在
      // 根据路由名称查询菜单信息
      const menusFound = await menuRepository.find({
        where: {
          [MenuEntityPropNameEnum.ROUTE_NAME]: menu[MenuEntityPropNameEnum.ROUTE_NAME]
        }
      });
      // 如果查询结果为空，则校验通过，或者查询出来的菜单信息中，只有当前要更新的菜单，也校验通过
      return menusFound.length === 0 || (menusFound.length === 1 && menusFound[0][MenuEntityPropNameEnum.ID] === menu[MenuEntityPropNameEnum.ID]);
    },
    message: `路由名称已存在或路由名称长度不合法（应在 ${MenuEntityPropValLimitConst[MenuEntityPropNameEnum.ROUTE_NAME].minLength} - ${MenuEntityPropValLimitConst[MenuEntityPropNameEnum.ROUTE_NAME].maxLength} 个字符之间）`
  },
  [MenuEntityPropNameEnum.ROUTE_PATH]: {
    verify: async (menu: Menu, menuRepository: Repository<Menu>) => {
      // 如果菜单类型不为目录菜单和 iframe，则无需校验路由路径
      if (
        menu[MenuEntityPropNameEnum.TYPE] !== MenuTypeEnum.DIR &&
        menu[MenuEntityPropNameEnum.TYPE] !== MenuTypeEnum.MENU &&
        menu[MenuEntityPropNameEnum.TYPE] !== MenuTypeEnum.IFRAME
      ) return true;
      // 如果不合法，则校验失败
      if (
        isNone(menu[MenuEntityPropNameEnum.ROUTE_PATH]) ||
        menu[MenuEntityPropNameEnum.ROUTE_PATH].length < MenuEntityPropValLimitConst[MenuEntityPropNameEnum.ROUTE_PATH].minLength ||
        menu[MenuEntityPropNameEnum.ROUTE_PATH].length > MenuEntityPropValLimitConst[MenuEntityPropNameEnum.ROUTE_PATH].maxLength ||
        !PathRegConst.ROUTE_PATH_REG.test(menu[MenuEntityPropNameEnum.ROUTE_PATH])
      ) return false;
      // 校验路由路径是否已存在
      // 根据路由路径查询菜单信息
      const menusFound = await menuRepository.find({
        where: {
          [MenuEntityPropNameEnum.ROUTE_PATH]: menu[MenuEntityPropNameEnum.ROUTE_PATH]
        }
      })
      // 如果查询结果为空，则校验通过，或者查询出来的菜单信息中，只有当前要更新的菜单，也校验通过
      return menusFound.length === 0 || (menusFound.length === 1 && menusFound[0][MenuEntityPropNameEnum.ID] === menu[MenuEntityPropNameEnum.ID]);
    },
    message: `路由路径不合法（符合规范外，长度还需应在 ${MenuEntityPropValLimitConst[MenuEntityPropNameEnum.ROUTE_PATH].minLength} - ${MenuEntityPropValLimitConst[MenuEntityPropNameEnum.ROUTE_PATH].maxLength} 个字符之间）`
  },
  [MenuEntityPropNameEnum.LINK_PATH]: {
    verify: async (menu: Menu) => {
      // 如果菜单类型不为 iframe 或外链，则无需校验链接路径
      if (
        menu[MenuEntityPropNameEnum.TYPE] !== MenuTypeEnum.IFRAME &&
        menu[MenuEntityPropNameEnum.TYPE] !== MenuTypeEnum.LINK
      ) return true;
      return !isNone(menu[MenuEntityPropNameEnum.LINK_PATH]) &&
        menu[MenuEntityPropNameEnum.LINK_PATH].length > 0 &&
        PathRegConst.LINK_PATH_REG.test(menu[MenuEntityPropNameEnum.LINK_PATH]);
    },
    message: "链接路径不合法"
  },
  [MenuEntityPropNameEnum.SORT]: {
    verify: async (menu: Menu) => {
      return !isNone(menu[MenuEntityPropNameEnum.SORT]) &&
        menu[MenuEntityPropNameEnum.SORT] >= MenuEntityPropValLimitConst[MenuEntityPropNameEnum.SORT].min &&
        menu[MenuEntityPropNameEnum.SORT] <= MenuEntityPropValLimitConst[MenuEntityPropNameEnum.SORT].max;
    },
    message: `菜单排序取值的范围应在 ${MenuEntityPropValLimitConst[MenuEntityPropNameEnum.SORT].min} - ${MenuEntityPropValLimitConst[MenuEntityPropNameEnum.SORT].max} 之间`
  },
  [MenuEntityPropNameEnum.ICON_TYPE]: {
    verify: async (menu: Menu) => {
      // 如果没有设置菜单图标类型，则直接校验通过
      if (isNone(menu[MenuEntityPropNameEnum.ICON_TYPE])) return true;
      // 如果设置了菜单图标类型，则校验图标类型是否合法
      return MenuEntityPropValLimitConst[MenuEntityPropNameEnum.ICON_TYPE].values.includes(menu[MenuEntityPropNameEnum.ICON_TYPE]);
    },
    message: "菜单图标类型不存在"
  },
  [MenuEntityPropNameEnum.LABEL_SORT]: {
    verify: async (menu: Menu) => {
      return !isNone(menu[MenuEntityPropNameEnum.LABEL_SORT]) &&
        menu[MenuEntityPropNameEnum.LABEL_SORT] >= MenuEntityPropValLimitConst[MenuEntityPropNameEnum.LABEL_SORT].min &&
        menu[MenuEntityPropNameEnum.LABEL_SORT] <= MenuEntityPropValLimitConst[MenuEntityPropNameEnum.LABEL_SORT].max;
    },
    message: `菜单标签页排序取值的范围应在 ${MenuEntityPropValLimitConst[MenuEntityPropNameEnum.LABEL_SORT].min} - ${MenuEntityPropValLimitConst[MenuEntityPropNameEnum.LABEL_SORT].max} 之间`
  }
};